package org.opens.dao;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import org.opens.entity.EduClass;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.Map;

/**
 * @Date 2020/12/30 21:15
 * @Created by 99126
 */
@Mapper
@Component
public interface EduClassDao extends BaseMapper<EduClass> {

    /**
     * 说明:
     * <pre>
     *     1. 该方法可以再插入数据后将数据库所生成的主键id设置到所保存的对象的主键上;
     *     2. 特别注意这个方法的返回值是受影响行数, 而不是返回主键自增的值.
     *     3. 这个方法只适用于mysql.
     * </pre>
     * @return 受影响行数
     */
    public Integer insertAndReturnPK(@Param(value = "param") EduClass eduClass);

    /**
     * 说明:
     * <pre>
     *     1. 使用selectKey的方式返回主键的值;
     *     2. 这个方法可以根据配置适用于不同的数据库, 当前配置适用于mysql.
     * </pre>
     * @return  受影响行数
     */
    public Integer insertAndReturnPKUseSelectKey(@Param(value = "param") EduClass eduClass);

    /**
     * 说明:
     * <pre>
     *     1. 在映射javabean的值到sql中时, 可以使用#{1}, #{2}这样很方便的语法进行取值, 但是不推荐经常这么做, 方便但是牺牲了可读性与
     *     可维护性.
     *     2. #{1}表示mapper的第一个参数, #{2}表示mapper的第二个参数, 以此类推, 在一个方法的参数超过3个时应该考虑封装而不是以这种方
     *     式继续开发.
     * </pre>
     */
    @Select(value = "select * from edu_class where class_id = #{1}")
    public EduClass findByIdUseIndexParam(Integer class_id);

    /**
     * 说明:
     * <pre>
     *     1. 这种方式和#{1}这种方式是基本相同的, 只是下标前面多了一个英文`param`；如果要取出第二个参数，就是#{param2}
     * </pre>
     */
    @Select(value = "select * from edu_class where class_id = #{param1}")
    public EduClass findByIdUseIndexParamAlias(Integer class_id);

    /**
     * 说明:
     * <pre>
     *     1. 这是推荐的方式, 这种方式可以给参数起别名, 与参数下标无关, 虽然写起来繁琐了一些, 但是提高了程序的可维护性.
     * </pre>
     */
    @Select(value = "select * from edu_class where class_id = #{class_id}")
    public EduClass findByIdUseParamName(@Param(value = "class_id") Integer class_id);

    /**
     * 说明：
     * <pre>
     *     1. 测试一对一查询；
     *     2. 假设这里EduClass和EduCourse的对应关系是通过EduClass的course_id描述一对一关系；
     * </pre>
     * @param class_id  所查询的班级
     */
    public EduClass findOneToOne(@Param(value = "class_id") Integer class_id);

    /**
     * 说明：
     * <pre>
     *     1. 测试一对多查询；
     *     2. 假设这里EduClass和Student的对应关系是通过Student的class_id描述一对多关系；
     * </pre>
     * @param class_id  所查询的班级
     */
    public EduClass findOneToMany(@Param(value = "class_id") Integer class_id);

    /**
     * 说明：
     * <pre>
     *     1. mybatis调用存储过程，将值设置到参数中去；
     *     2. 这个方法的返回值是无效的。
     *     3. 创建存储过程的sql为：
     *     ```
     *      drop PROCEDURE if EXISTS select_edu_class_by_id;
     *      create PROCEDURE select_edu_class_by_id(
     *      in classId bigint,
     *      out className varchar(50),
     *      out createDate TIMESTAMP,
     *      out courseId bigint
     *      )
     *      begin
     *      select class_name, create_date, course_id into className, createDate, courseId
     *      from edu_class
     *      where class_id = classId;
     *      end;
     *     ```
     * </pre>
     */
    public EduClass findByIdUseProcedure(EduClass eduClass);

    /**
     * 说明：
     * <pre>
     *     1. 这个存储过程用来分页查询，存储过程也是可以有返回值的，需要搭配resultMap来做映射，相当于这个存储过程有两个输出的地方：
     *      - 输出到参数；
     *      - 输出到函数返回值；
     *     2. 调用存储过程后，如果参数类型是map，则会把输出参数（mode=OUT）put到map中；
     *     3. 创建存储过程的sql：
     *     ```
     *      drop PROCEDURE if EXISTS select_edu_class_page;
     *      create PROCEDURE select_edu_class_page(
     *      IN className varchar(50),
     *      IN _offset BIGINT,
     *      IN _limit BIGINT,
     *      OUT total BIGINT
     *      )
     *      begin
     *      # 查询数据总数
     *      select count(1) into total
     *      from edu_class
     *      where class_name like concat('%', className, '%');
     *      # 分页查询数据
     *      select *
     *      from edu_class
     *      where class_name like concat('%', className, '%')
     *      limit _offset, _limit;
     *      end;
     *     ```
     * </pre>
     */
    public List<EduClass> pageUseProcedure(Map<String, Object> param);

    /**
     * 说明：
     * <pre>
     *     1. 这个存储过程最简单，代码如下：
     *     ```
     *      drop PROCEDURE if EXISTS delete_edu_class;
     *      create PROCEDURE delete_edu_class(
     *      IN classId BIGINT
     *      )
     *      begin
     *      delete from edu_class where class_id = classId;
     *      end;
     *     ```
     * </pre>
     * @param classId   要删除的班级id
     * @return  受影响行数
     */
    public int deleteUseProcedure(@Param(value = "classId") Integer classId);

    /**
     * 说明：
     * <pre>
     *     1. 调用这个存储过程进行插入；
     *     2. sql代码：
     *     ```
     *      drop PROCEDURE if EXISTS insert_edu_class;
     *      create PROCEDURE insert_edu_class(
     *      OUT classId BIGINT,
     *      IN className varchar(50),
     *      IN courseId BIGINT,
     *      OUT createDate TIMESTAMP
     *      )
     *      BEGIN
     *      IF createDate is null then
     *      	set createDate = NOW();
     *      END IF;
     *      insert into edu_class(class_name, course_id, create_date) values(className, courseId, createDate);
     *      select LAST_INSERT_ID() into classId;
     *      END;
     *     ```
     * </pre>
     * @param eduClass  主要是传入insert时的一些必须参数和容纳返回值；
     * @return  受影响行数
     */
    public int insertUseProcedure(EduClass eduClass);

}
